package com.ihr360.payroll.service.salarytask.convertor;

import com.ihr360.commons.lang.CollectionUtils;
import com.ihr360.commons.model.IConvertor;
import com.ihr360.payroll.entity.task.PayPeriodEntity;
import com.ihr360.payroll.entity.task.PayPeriodTermEntity;
import com.ihr360.payroll.model.dto.salary.embeddable.RefServiceStatistics;
import com.ihr360.payroll.model.dto.salary.plan.SalaryPlan;
import com.ihr360.payroll.model.dto.salary.task.period.ActivePayPeriod;
import com.ihr360.payroll.model.dto.salary.task.period.PayPeriodTerm;
import com.ihr360.payroll.type.PeriodState;
import com.ihr360.payroll.type.ReportState;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class PayPeriodConvertor implements IConvertor<PayPeriodEntity, ActivePayPeriod> {
    @Override
    public ActivePayPeriod convertEntityToDto(PayPeriodEntity entity) {

        final ActivePayPeriod period = new ActivePayPeriod();
        period.setId(entity.getId());

        SalaryPlan plan = SalaryPlan.builder().build();
        plan.setId(entity.getPlanId());
        period.setSalaryPlan(plan);

        period.setStartOn(entity.getStartOn());
        period.setEndOn(entity.getEndOn());
        period.setAttendanceStartOn(entity.getAttendanceStartOn());
        period.setAttendanceEndOn(entity.getAttendanceEndOn());

        List<PayPeriodTermEntity> terms = entity.getTerms();
        List<PayPeriodTerm> periodTerms = new ArrayList<>(terms.size());
        int index = 1;
        for (PayPeriodTermEntity t : terms) {
            PayPeriodTerm term = new PayPeriodTerm();
            BeanUtils.copyProperties(t, term);
            term.setPayPeriod(period);
            term.setState(PeriodState.STAFF_CHECKING);
            term.setReportState(ReportState.UNSTARTED);
            term.setPayslipState(ReportState.UNSTARTED);
            term.setTermIndex(index);
            index++;
            periodTerms.add(term);
        }
        period.setTerms(periodTerms);
        return period;
    }

    @Override
    public PayPeriodEntity convertDtoToEntity(ActivePayPeriod dto) {

        List<PayPeriodTermEntity> periodTermEntities =
                dto.getTerms().stream().map(this::convertPayPeriodTermToEntity)
                        .collect(Collectors.toList());

        PayPeriodTerm currentPeriodTerm = dto.getCurrentTerm();
        PayPeriodTermEntity currentPeriodTermEntity = convertPayPeriodTermToEntity(currentPeriodTerm);

        PayPeriodEntity resultEntity = PayPeriodEntity.builder()
                .endOn(dto.getEndOn())
                .startOn(dto.getStartOn())
                .year(dto.getYear())
                .month(dto.getMonth())
                .attendanceEndOn(dto.getAttendanceEndOn())
                .attendanceStartOn(dto.getAttendanceStartOn())
                .planId(dto.getSalaryPlan().getId())
                .planName(dto.getSalaryPlan().getName())
                .planPrivilege(dto.getSalaryPlan().getResourceAccess().getAccessPrivilege())
                .planMonthCycle(dto.getSalaryPlan().isMonthCycle())
                .count(dto.getSalaryPlan().getPayPeriodStaffNumber())
                .state(dto.getState())
                .applicationId(dto.getApplicationId())
                .terms(periodTermEntities)
                .currentTermId(currentPeriodTermEntity == null ? null : currentPeriodTermEntity.getId())
                .currentTermJobExcutionIds(dto.getCurrentTerm().getJobExecutionIds() == null
                        ? Collections.emptyList()
                        : dto.getCurrentTerm().getJobExecutionIds().getJobExecutionIds())
                .build();
        resultEntity.setId(dto.getId());
        return resultEntity;
    }

    public PayPeriodTermEntity convertPayPeriodTermToEntity(PayPeriodTerm t) {
        if (t == null) {
            return null;
        }
        PayPeriodTermEntity term = new PayPeriodTermEntity();
        BeanUtils.copyProperties(t, term);
        RefServiceStatistics refServiceStatistics = t.getRefServiceStatistics();
        if (refServiceStatistics != null) {
            term.setRefSihf(refServiceStatistics.getRefSihf());
            term.setSihfNotOkCount(refServiceStatistics.getSihfNotOkCount());
            term.setRefAttendance(refServiceStatistics.getRefAttendance());
            term.setAttendanceNotOkCount(refServiceStatistics.getAttendanceNotOkCount());
        }
        return term;
    }

    public List<PayPeriodEntity> convertDtosToEntities(List<ActivePayPeriod> dtos) {
        if (CollectionUtils.isEmpty(dtos)) {
            return Collections.emptyList();
        }
        List<PayPeriodEntity> vos = new ArrayList<>(dtos.size());
        dtos.forEach(dto -> vos.add(convertDtoToEntity(dto)));
        return vos;
    }

    public List<ActivePayPeriod> convertEntitiesToDtos(List<PayPeriodEntity> vos) {
        if (CollectionUtils.isEmpty(vos)) {
            return Collections.emptyList();
        }
        List<ActivePayPeriod> dtos = new ArrayList<>(vos.size());
        vos.forEach(vo -> dtos.add(convertEntityToDto(vo)));
        return dtos;
    }
}